1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31 import java.awt.*;
32 import java.lang.reflect.Method;
33 import java.util.concurrent.Callable;
34 import java.util.concurrent.FutureTask;
35 import java.util.concurrent.TimeUnit;
36
37 import javax.swing.JComponent;
38 import javax.swing.JButton;
39 import javax.swing.JFrame;
40 import javax.swing.RepaintManager;
41 import javax.swing.SwingUtilities;
42
43
44
45 public class bug6608456 {
46 private static final TestFuture testFuture = new TestFuture();
47 public static void main(String[] args) throws Exception {
48 final JComponent component = invokeAndWait(
49 new Callable<JComponent>() {
50 public JComponent call() throws Exception {
51 RepaintManager.setCurrentManager(new TestRepaintManager());
52 JFrame frame = new JFrame("test");
53 frame.setLayout(new FlowLayout());
54 JButton button = new JButton("default");
55
56 frame.add(button);
57 button = new JButton("delegate");
58 if ( ! registerDelegate(
59 button, new TestRepaintManager())) {
60 return null;
61 }
62 frame.add(button);
63 frame.pack();
64 frame.setVisible(true);
65 return button;
66 }
67 });
68 if (component == null) {
69 throw new RuntimeException("failed. can not register delegate");
70 }
71 blockTillDisplayed(component);
72
73 invokeAndWait(
74 new Callable<Void>() {
75 public Void call() {
76 component.repaint();
77 return null;
78 }
79 });
80 try {
81 if (testFuture.get(10, TimeUnit.SECONDS)) {
82
83 }
84 } catch (Exception e) {
85 throw new RuntimeException("failed", e);
86 } finally {
87 JFrame frame = (JFrame) SwingUtilities
88 .getAncestorOfClass(JFrame.class, component);
89 if (frame != null) {
90 frame.dispose();
91 }
92 }
93 }
94 static class TestRepaintManager extends RepaintManager {
95 @Override
96 public void addDirtyRegion(JComponent c, int x, int y, int w, int h) {
97 if (RepaintManager.currentManager(c) == this) {
98 testFuture.defaultCalled();
99 } else {
100 testFuture.delegateCalled();
101 }
102 super.addDirtyRegion(c, x, y, w, h);
103 }
104 }
105 static class TestFuture extends FutureTask<Boolean> {
106 private volatile boolean defaultCalled = false;
107 private volatile boolean delegateCalled = false;
108 public TestFuture() {
109 super(new Callable<Boolean>() {
110 public Boolean call() {
111 return null;
112 }
113 });
114 }
115 public void defaultCalled() {
116 defaultCalled = true;
117 updateState();
118 }
119 public void delegateCalled() {
120 delegateCalled = true;
121 updateState();
122 }
123 private void updateState() {
124 if (defaultCalled && delegateCalled) {
125 set(Boolean.TRUE);
126 }
127 }
128 }
129
130 private static boolean registerDelegate(JComponent c,
131 RepaintManager repaintManager) {
132 boolean rv = false;
133 try {
134 Class<?> clazz = Class.forName("com.sun.java.swing.SwingUtilities3");
135 Method method = clazz.getMethod("setDelegateRepaintManager",
136 JComponent.class, RepaintManager.class);
137 method.invoke(clazz, c, repaintManager);
138 rv = true;
139 } catch (Exception ignore) {
140 }
141 return rv;
142 }
143 static <T> T invokeAndWait(Callable<T> callable) throws Exception {
144 FutureTask<T> future = new FutureTask<T>(callable);
145 SwingUtilities.invokeLater(future);
146 return future.get();
147 }
148
149 public static void blockTillDisplayed(Component comp) {
150 Point p = null;
151 while (p == null) {
152 try {
153 p = comp.getLocationOnScreen();
154 } catch (IllegalStateException e) {
155 try {
156 Thread.sleep(100);
157 } catch (InterruptedException ie) {
158 }
159 }
160 }
161 }
162 }